<?php

	// +----------------------------------------------------------------------
	// | 公众号对接
	// +----------------------------------------------------------------------
	// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
	// +----------------------------------------------------------------------
	// | Author: 微尘 <yicmf@qq.com>
	// +----------------------------------------------------------------------

	namespace app\controller\api\notify;

	use app\wechat\model\WechatAccount as WechatAccountModel;
    use app\wechat\model\WechatFans as WechatFansModel;
    use app\wechat\model\WechatMenu as WechatMenuModel;
    use app\wechat\model\WechatMsg as WechatMsgModel;
    use app\wechat\model\WechatReply as WechatReplyModel;
    use think\App;
    use think\Exception;
    use think\facade\Event;
    use think\facade\Log;
    use wechat\message\Image as WechatMsgImage;
    use wechat\message\News as WechatMsgNews;
    use wechat\message\Text as WechatMsgText;
    use wechat\official_account\Media as WechatServerMedia;
    use wechat\official_account\Server as ServerOfficialAccount;
    use wechat\official_account\Template as TemplateOfficial;
    use wechat\official_account\User as UserOfficial;

    class WechatOfficial
	{

		/**
		 * 应用实例
		 * @var App
		 */
		protected $app;

		/**
		 * @var WechatFansModel
		 */
		private $fans = null;

		/**
		 * Request实例
		 * @var \think\Request
		 */
		protected $request;

		/**
		 * 留言模型
		 * @var WechatMsgModel
		 */
		private $leaveWord = null;

		/**
		 * 留言模型
		 * @var WechatAccountModel
		 */
		private $account = null;
		private $word;
		/**
		 * 用户openid
		 */
		private $openid = null;
		/**
		 * @var ServerOfficialAccount
		 */
		private $service = null;


		/**
		 * 构造方法
		 * @access public
		 */
		public function __construct(App $app = null)
		{
			$this->app = $app;
			$this->request = $this->app['request'];
			if ($this->request->has('id')) {
				$this->account = WechatAccountModel::where('id', $this->request->param('id'))->find();
			} else {
				$this->account = WechatAccountModel::where('status', 1)->where('is_default', 1)->find();
			}

			$service = new ServerOfficialAccount();
			$this->service = $service->initAccount($this->account);
		}

		public function test()
		{

			$oa = new TemplateOfficial();
			$oa->initAccount($this->account);
//            $WechatTemplate = WechatTemplateModel::where('wechat_no', 'OPENTM401627381')->where('status', 1)->find();
			$data = [
				'first' => ['value' => '成功', 'color' => '#000000'],
				'number' => ['value' => '1', 'color' => '#000000'],
				//                'keyword1'=> ['value'=>$auth['idcard_name'], 'color'=>'#000000'],
				//                'keyword2'=> ['value'=>time_format(), 'color'=>'#000000'],
				'remark' => ['value' => '如果有疑问，请联系客服！', 'color' => '#000000'],
			];
			//            $oa->send('o7ldnuMTe7Ifj1yFa7iW9aP9d5lw', $WechatTemplate['template_id'],
			//                url('mobile/User/auth',[],true,true),
			//                $param);
			$re = $oa->send('o7ldnuMTe7Ifj1yFa7iW9aP9d5lw', '0sL1x8Gk3bl9AN3VDM3ONPN4mXuVAlUVClkmb3etSwI', $data, '');
			dump($re);
		}

		/**
		 * 微信消息入口
		 * @return bool|mixed|string
		 * @throws \Exception
		 * @author 微尘 <yicmf@qq.com>
		 */
		public function index()
		{
			try {
				$this->service->check();
				// 获取消息来源用户OPENID
				$this->openid = $this->service->getOpenid();
				// 获取并同步粉丝信息到数据库
				$this->_setFan(true);
				if ('event' == $this->service->getMsgType()) {
					$reply = $this->_event();
				} else {
					$reply = $this->_receive();
				}
				if (empty($reply)) {
					$reply = '服务器开小差了，请稍候再试';
				}
			} catch (Exception $e) {
				$reply = $e->getMessage();
			}
			$reply = $this->_replyConvert($reply);
			if ($reply == 'success') {
				return $reply;
			} else {
				return $this->service->reply($reply)->send();
			}
		}

		/**
		 * 消息处理
		 */
		protected function _receive()
		{
			$this->word['event'] = 'keys';
			// 分别执行对应类型的操作

			$method = '_receive' . ucwords($this->service->getMsgType());
			if (method_exists($this, $method)) {
				$reply = $this->$method();
			} else {
				$reply = $this->_receiveDefault();
			}
			if (!$reply) {
				$reply = $this->_keyReply($this->service->getMsgType(), $this->service->getContent());
			}
			return $reply;
		}

		/**
		 * 事件处理
		 */
		protected function _event()
		{
			$event = $this->service->getEvent();
			$this->word['event'] = strtolower($event['event']);
			switch (strtolower($event['event'])) {
				case 'subscribe': // 粉丝关注事件
					$this->_spread($event['key']);
					$reply = $this->_eventReply(strtolower($event['event']), $event['key']);
					break;
				case 'unsubscribe':// 粉丝取消关注
					$this->_setFan(false);
					$reply = 'success';
					break;
				case 'click': // 点击菜单事件
					$reply = $this->_eventClick($event['key']);
					break;
				case 'scancode_push':
				case 'scancode_waitmsg': // 扫码推事件
					$scanInfo = $this->service->getScanInfo();
					if (isset($scanInfo['ScanResult'])) {
						$this->word['content'] = $scanInfo['ScanResult'];
						$reply = $this->_eventReply(strtolower($event['event']), $scanInfo['ScanResult']);
					} else {
						$reply = 'success';
					}
					break;
				case 'scan':// 已经关注扫码
					if (!empty($event['key'])) {
						$this->_spread($event['key']);
						$reply = $this->_eventReply(strtolower($event['event']), $event['key']);
					} else {
						$reply = 'success';
					}
					break;
				default:
					$reply = $this->_eventReply(strtolower($event['event']), $event['key']);
			}
			return $reply;
		}

		/**
		 * 推荐好友扫码关注
		 * @param string $event
		 * @return mixed
		 */
		private function _spread($event)
		{
//			$key = preg_replace('|^.*?(\d+).*?$|', '$1', "{$event}");
//			// 检测推荐是否有效
//			$fans = Db::name('WechatFans')->where('id', $key)->find();
//			if (!is_array($fans) || !isset($fans['openid']) || $fans['openid'] === $this->openid) {
//				return false;
//			}
//			// 标识推荐关系
//			$data = ['spread_openid' => $fans['openid'], 'spread_at' => date('Y-m-d H:i:s')];
//			Db::name('WechatFans')->where("openid='{$this->openid}' and (spread_openid is null or spread_openid='')")->update($data);
		}

		/**
		 * 响应回复
		 * @param string $event
		 * @param string $content
		 * @return string|WechatReplyModel
		 */
		private function _eventReply($event, $content)
		{
			$this->word['event'] = $event;
			///完整匹配
			$reply = WechatReplyModel::where('main_event', $event)
				->where('keys', $content)->where('matching', 1)
				->order('sort ASC')->where('status', 1)->find();
			// 默认
			if (!$reply) {
				// 统一处理
				$reply = WechatReplyModel::where('main_event', 'all')->where('status', 1)->find();
			}
			return $reply;
		}

		/**
		 * 响应回复
		 * @param string $receive_type
		 * @param string $content
		 * @return string|WechatReplyModel
		 */
		private function _keyReply($receive_type, $content)
		{
			///完整匹配
			$reply = WechatReplyModel::where('main_event', 'keys')
				->where('keys', $content)
				->where('receive_type', $receive_type)
				->where('matching', 1)
				->order('sort ASC')->where('status', 1)->find();
			// 模糊匹配
			if (!$reply) {
				// 模糊一条消息
				$reply = WechatReplyModel::where('main_event', 'keys')
					->where('receive_type', $receive_type)
					->where('keys', 'like', '%' . $content . '%')
					->order('sort ASC')->where('matching', 0)
					->where('status', 1)->find();
			}
			// 默认
			if (!$reply) {
				// 统一处理
				$reply = WechatReplyModel::where('main_event', 'all')->where('status', 1)->find();
			}
			return $reply;
		}

		/**
		 * 解析回复消息
		 * @param $reply
		 * @return mixed|string|WechatMsgNews|WechatMsgText
		 * @throws Exception
		 */
		private function _replyConvert($reply)
		{

			if (is_object($reply)) {
				$this->word['wechat_reply_id'] = $reply['id'];
				$reply['times'] = $reply['times'] + 1;
				$reply->isAutoWriteTimestamp(false)->save();
				if ('text' == $reply['type']) {
					$content = $reply['content'];
					if ($reply['content'] && $reply['content'] !== 'success') {
						$content = new WechatMsgText();
						$content->setContent($reply['content']);
					}
				} elseif ('image' == $reply['type']) {
					// 回复图片
					$media = new WechatServerMedia();
					$media->initAccount($this->account);
					$result = $media->uploadImage($reply['image']['path']);
					if (is_array($result) && isset($result['errmsg'])) {
						Log::write($result['errmsg']);
						$content = new WechatMsgText();
						$content->setContent('系统故障，请稍候再试');
					} else {
						$content = new WechatMsgImage();
						$content->setMediaId($result['media_id']);

						$content = new WechatMsgNews();

						$content->setArticle('你好', 'miaoshu', $reply['image']['path'], $reply['image']['path']);

					}
				} elseif ('none' == $reply['type']) {
					// 回复图片
					$content = 'success';
				} elseif ('news' == $reply['type']) {
					// 回复图片
					$media = new WechatServerMedia();
					$media->initAccount($this->account);
					$result = $media->uploadImage($reply['image']['path']);
					if (is_array($result) && isset($result['errmsg'])) {
						Log::write($result['errmsg']);
						$content = new WechatMsgText();
						$content->setContent('系统故障，请稍候再试');
					} else {
						$content = new WechatMsgNews();
						$content->setArticle($reply['title'], $reply['description'], $reply['image']['url'], $reply['url']);
					}
				} else {
					$content = '未知';
				}
			} else {
				$content = $reply;
			}
			if (isset($this->word['content'])) {
				$this->word['type'] = $this->service->getMsgType();
				$this->word['reply'] = $content;
				$this->word['wechat_account_id'] = $this->account['id'];
				$this->word['wechat_fans_id'] = $this->fans['id'];
				$this->word['reply_time'] = time_format();
				WechatMsgModel::create($this->word);
			}
			return $content;
		}

		/**
		 * 接收文本消息
		 * @return mixed
		 * @author 微尘 <yicmf@qq.com>
		 * @datetime: 2020/5/11 14:29
		 */
		private function _receiveText()
		{
			$content = $this->service->getContent();
			$this->word['content'] = $content;
			return Event::trigger('wechat_receive_text', ['content' => $content, 'openid' => $this->openid], true);
		}


		/**
		 * 未定义事件处理
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _receiveDefault()
		{
			$this->word['content'] = '未定义消息';
			return false;
		}

		/**
		 * 收到地址
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _receiveLocation()
		{
			$message = $this->service->getReceive();
			$this->word['content'] = '粉丝发送地址：X' . $message['Location_X'] . '，Y：' . $message['Location_Y'] . '，详情：' . $message['Label'];
			$this->word['media_id'] = $message['Location_X'] . ',' . $message['Location_Y'];
			return false;
		}

		/**
		 * 收到图片
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _receiveImage()
		{
			$this->word['content'] = '用户图片留言' . $this->service->getPicUrl();
			$this->word['media_id'] = $this->service->getMediaId();
			return false;
		}

		/**
		 * 收到语音
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _receiveVoice()
		{
			$this->word['content'] = '用户语音留言' . $this->service->getMediaId();
			$this->word['media_id'] = $this->service->getMediaId();
			return false;
		}

		/**
		 * 收到视频
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _receiveVideo()
		{
			$this->word['content'] = '用户视频留言' . $this->service->getMediaId();
			$this->word['media_id'] = $this->service->getMediaId();
			return false;
		}

		/**
		 * 收到视频
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _receiveLink()
		{
			$this->word['content'] = '用户链接消息' . $this->service->getUrl();
			return false;
		}

		/**
		 *设置当前用户
		 * @param bool $subscribe
		 */
		private function _setFan($subscribe = true)
		{
			$event = $this->service->getEvent();
			if (strtolower($event['event']) == 'unsubscribe') {
				$subscribe = false;
			}

			$fans = WechatFansModel::where('openid', $this->openid)->find();
			if ($subscribe) {
				$UserOfficial = new UserOfficial();
				$UserOfficial->initAccount($this->account);
				$user = $UserOfficial->userInfo($this->openid);
				if ($fans) {
					$this->fans = $fans;
				} else {
					$fans = [];
					$fans['nickname'] = $user['nickname'];
					$fans['city'] = $user['city'];
					$fans['city'] = $user['city'];
					$fans['openid'] = $user['openid'];
					$fans['province'] = $user['province'];
					$fans['country'] = $user['country'];
					$fans['subscribe_time'] = time_format($user['subscribe_time']);
					$fans['headimgurl'] = $user['headimgurl'];
					$fans['subscribe_scene'] = $user['subscribe_scene'];
					$fans['sex'] = $user['sex'];
					$fans['language'] = $user['language'];
					$fans['groupid'] = $user['groupid'];
					$fans['qr_scene'] = $user['qr_scene'];
					$fans['qr_scene_str'] = $user['qr_scene_str'];
					$fans['remark'] = $user['remark'];
					if (isset($user['unionid'])) {
						$fans['unionid'] = $user['unionid'];
					}
					$this->fans = WechatFansModel::create($fans);

				}
			} else {
				if ($fans) {
					$fans['unsubscribe_time'] = time_format();
					$fans['status'] = time_format();
					$fans->save();
				}
			}

		}


		/**
		 * 点击菜单
		 * @param $key
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _eventClick($key)
		{
			$menu = WechatMenuModel::where('id', $key)->find();
			if ($menu) {
				return $this->_eventReply('keys', $menu['key']);
			} else {
				Log::record('点击菜单，key：' . $key);
				return 'success';
			}
		}


		/**
		 * 默认事件
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _eventDefault($event)
		{
			Log::record('事件操作' . $event);
			return 'success';
		}

		/**
		 * 模板消息发送完毕，记录成功与失败
		 * @param $message
		 * @return string
		 * @author 微尘 <yicmf@qq.com>
		 */
		private function _eventTemplatesendjobfinish($message)
		{
			/**
			 * <xml>
			 * <ToUserName><![CDATA[gh_7f083739789a]]></ToUserName>
			 * <FromUserName><![CDATA[oia2TjuEGTNoeX76QEjQNrcURxG8]]></FromUserName>
			 * <CreateTime>1395658984</CreateTime>
			 * <MsgType><![CDATA[event]]></MsgType>
			 * <Event><![CDATA[TEMPLATESENDJOBFINISH]]></Event>
			 * <MsgID>200163840</MsgID>
			 * <Status><![CDATA[failed:user block]]></Status>
			 * </xml>
			 */
			return '模板消息发送完毕';
		}


	}
